package com.krain.corelibrary.util;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.TextUtils;
import android.widget.ImageView;

import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
import com.squareup.picasso.Target;

import java.io.File;

/**
 * 图片加载类。<br>
 * 目前Picasso最新版本为2.5.2, 但加载本地大图片会有bug， 所以使用2.4.0
 * bug：https://github.com/square/picasso/issues/364
 */
public class ImageLorder {

    private Context mContext;
    private static ImageLorder imageLoader;
    private Picasso mPicasso;
    private int mErrorResId;

    /**
     * 初始化ImageLoader， size为了兼容之前的构造方法，等待使用成熟后取出
     *
     * @param context
     */
    private ImageLorder(Context context) {
        // TODO
        this.mContext = context;
        // Generate the global default Picasso instance.
        this.mPicasso = Picasso.with(context);
    }

    public static synchronized ImageLorder getInstance(Context context) {

        if (imageLoader == null)
            imageLoader = new ImageLorder(context);
        return imageLoader;
    }

    /**
     * An error drawable to be used if the request image could not be loaded.
     *
     * @param errorResId
     */
    public void setErrorResId(int errorResId) {
        this.mErrorResId = errorResId;
    }

    /**
     * <br>
     * In most cases, you should use this when you are dealing with a custom View or view holder
     * which should implement the Target interface.
     * <p/>
     * <p/>
     * Implementing on a View: <br>
     * {@code
     * public class ProfileView extends FrameLayout implements Target {
     *
     * @param filePathOrUrl
     * @param target
     * @Override public void onBitmapLoaded(Bitmap bitmap, LoadedFrom from) {
     * setBackgroundDrawable(new BitmapDrawable(bitmap));
     * }
     * @Override public void onBitmapFailed() {
     * setBackgroundResource(R.drawable.profile_error);
     * }
     * @Override public void onPrepareLoad(Drawable placeHolderDrawable) {
     * frame.setBackgroundDrawable(placeHolderDrawable);
     * }
     * }
     * }
     * </p>
     * <p/>
     * <p/>
     * Implementing on a view holder object for use inside of an adapter: <br>
     * {@code
     * public class ViewHolder implements Target {
     * public FrameLayout frame;
     * public TextView name;
     * @Override public void onBitmapLoaded(Bitmap bitmap, LoadedFrom from) {
     * frame.setBackgroundDrawable(new BitmapDrawable(bitmap));
     * }
     * @Override public void onBitmapFailed() {
     * frame.setBackgroundResource(R.drawable.profile_error);
     * }
     * @Override public void onPrepareLoad(Drawable placeHolderDrawable) {
     * frame.setBackgroundDrawable(placeHolderDrawable);
     * }
     * }
     * }
     * </p>
     */
    public void fetchImage(String filePathOrUrl, Target target) {
        RequestCreator creator = getRequestCreator(filePathOrUrl);
        creator.into(target);
    }

    /**
     * 通过文件路径或者Url加载图片
     *
     * @param imageView     Asynchronously fulfills the request into the specified ImageView.
     * @param filePathOrUrl Start an image request using the specified path.
     */
    public void loadImage(Context context, final ImageView imageView, String filePathOrUrl) {
        loadImage(context, imageView, filePathOrUrl, 0);
    }

    /**
     * 通过文件路径或者Url加载图片，未加载完成前显示占位资源
     *
     * @param imageView        Asynchronously fulfills the request into the specified ImageView.
     * @param filePathOrUrl    Start an image request using the specified path.
     * @param placeholderResId A placeholder drawable to be used while the image is being loaded.
     */
    public void loadImage(Context context, final ImageView imageView, String filePathOrUrl, int placeholderResId) {
        loadImage(context, imageView, filePathOrUrl, placeholderResId, null);
    }

    public void loadImage(Context context, final ImageView imageView, String filePathOrUrl, Callback callback) {
        loadImage(context, imageView, filePathOrUrl, 0, callback);
    }

    /**
     * 通过文件路径或者Url加载图片，未加载完成前显示占位资源，占位资源不能为0.<br>
     * <br>
     * Note: The Callback param is a strong reference and will prevent your Activity or Fragment from being garbage collected.
     * If you use this method, it is strongly recommended you invoke an adjacent Picasso.cancelRequest(android.widget.ImageView) call to prevent temporary leaking.
     *
     * @param imageView        Asynchronously fulfills the request into the specified ImageView.
     * @param filePathOrUrl    Start an image request using the specified path.
     * @param placeholderResId A placeholder drawable to be used while the image is being loaded.
     * @param callback
     */
    public void loadImage(Context context, final ImageView imageView, String filePathOrUrl, int placeholderResId, Callback callback) {
        if (filePathOrUrl == null || TextUtils.isEmpty(filePathOrUrl.trim())) {
            loadImage(imageView, placeholderResId);
        } else {
            loadImage(context, imageView, getRequestCreator(filePathOrUrl), placeholderResId, callback);
        }
    }

    public void loadImage(Context context, final ImageView imageView, String filePathOrUrl, int placeholderResId, int width, int height) {
        loadImage(context, imageView, filePathOrUrl, placeholderResId, width, height, false);
    }

    public void loadImage(Context context, final ImageView imageView, String filePathOrUrl, int placeholderResId, int width, int height, boolean isNeedCut) {
        loadImage(context, imageView, filePathOrUrl, placeholderResId, width, height, isNeedCut, null);
    }

    /**
     * 通过文件加载图片
     *
     * @param imageView Asynchronously fulfills the request into the specified ImageView.
     * @param file      Start an image request using the specified image file.
     */
    public void loadImage(Context context, final ImageView imageView, File file) {
        loadImage(context, imageView, file, 0);
    }

    /**
     * 通过文件加载图片，未加载完成前显示占位资源
     *
     * @param imageView        Asynchronously fulfills the request into the specified ImageView.
     * @param file             Start an image request using the specified image file.
     * @param placeholderResId A placeholder drawable to be used while the image is being loaded.
     */
    public void loadImage(Context context, final ImageView imageView, File file, int placeholderResId) {
        loadImage(context, imageView, file, placeholderResId, null);
    }

    /**
     * 通过文件加载图片，未加载完成前显示占位资源，无占位资源id为0.<br>
     * <br>
     * Note: The Callback param is a strong reference and will prevent your Activity or Fragment from being garbage collected.
     * If you use this method, it is strongly recommended you invoke an adjacent Picasso.cancelRequest(android.widget.ImageView) call to prevent temporary leaking.
     *
     * @param imageView        Asynchronously fulfills the request into the specified ImageView.
     * @param file             Start an image request using the specified image file.
     * @param placeholderResId A placeholder drawable to be used while the image is being loaded.
     * @param callback
     */
    public void loadImage(Context context, final ImageView imageView, File file, int placeholderResId, Callback callback) {
        if (file == null || !file.exists()) {
            loadImage(imageView, placeholderResId);
        } else {
            loadImage(context, imageView, mPicasso.load(file), placeholderResId, callback);
        }
    }

    /**
     * 通过资源文件加载图片
     *
     * @param imageView  Asynchronously fulfills the request into the specified ImageView.
     * @param resourceId Start an image request using the specified drawable resource ID.
     */
    public void loadImage(final ImageView imageView, int resourceId) {
        loadImage(imageView, resourceId, null);
    }

    /**
     * 通过资源文件加载图片，未加载完成前显示占位资源，无占位资源id为0.<br>
     * <br>
     * Note: The Callback param is a strong reference and will prevent your Activity or Fragment from being garbage collected.
     * If you use this method, it is strongly recommended you invoke an adjacent Picasso.cancelRequest(android.widget.ImageView) call to prevent temporary leaking.
     *
     * @param imageView  Asynchronously fulfills the request into the specified ImageView.
     * @param resourceId Start an image request using the specified drawable resource ID.
     * @param callback
     */
    public void loadImage(final ImageView imageView, int resourceId, Callback callback) {
        if (resourceId <= 0) {
            return;
        }
        loadImage(mContext, imageView, mPicasso.load(resourceId), 0, callback);
    }

    public void loadImage(Context context, final ImageView imageView, RequestCreator requestCreator, int placeholderResId, Callback callback) {
        if (placeholderResId != 0) {
            requestCreator.placeholder(placeholderResId);
        }

        if (context != null) {
            requestCreator.tag(context);
        }
        requestCreator.into(imageView, callback);
    }

    public void loadImage(Context context, final ImageView imageView, File file, int placeholderResId, int width, int height,
                          boolean isNeedCut, Callback callback) {
        RequestCreator creator = mPicasso.load(file);
        loadImage(context, imageView, creator, placeholderResId, width, height, isNeedCut, callback);
    }

    public void loadImage(Context context, final ImageView imageView, String filePathOrUrl, int placeholderResId, int width, int height,
                          boolean isNeedCut, Callback callback) {
        if (filePathOrUrl == null || TextUtils.isEmpty(filePathOrUrl.trim())) {
            loadImage(imageView, placeholderResId);
            return;
        }

        RequestCreator creator = getRequestCreator(filePathOrUrl);
        loadImage(context, imageView, creator, placeholderResId, width, height, isNeedCut, callback);
    }

    public void loadImage(Context context, final ImageView imageView, RequestCreator creator, int placeholderResId, int width, int height,
                          boolean isNeedCut, Callback callback) {
        if (placeholderResId != 0) {
            creator.placeholder(placeholderResId);
        }

        if (width != 0 && height != 0) {
            creator.resize(width, height);
        }

        if (isNeedCut) {
            creator.centerCrop();
        } else {
            creator.centerInside();
        }

        if (context != null) {
            creator.tag(context);
        }

        if (mErrorResId != 0) {
            creator.error(mErrorResId);
        }
        creator.into(imageView, callback);
    }

    public RequestCreator getRequestCreator(String filePathOrUrl) {
        File file = new File(filePathOrUrl);

        // why load Uri - https://github.com/square/picasso/issues/1069
        if (file != null && file.exists()) {
            return mPicasso.load(Uri.fromFile(file));
        }

        return mPicasso.load(filePathOrUrl);
    }

    /**
     * 暂停加载图片
     *
     * @param context
     */
    public void pause(Context context) {
        mPicasso.pauseTag(context);
    }

    /**
     * 恢复加载图片
     *
     * @param context
     */
    public void resume(Context context) {
        mPicasso.resumeTag(context);
    }


    public Picasso getmPicasso() {
        return mPicasso;
    }
}
